package awt.robot;

import java.awt.Toolkit;

import sun.awt.SunToolkit;

import util.ReflectUtils;

/**
 * System is idle in EDT point of view if there is no event currently processing and there are no events pending in queue.
 * 
 * @author Mykhaylo Adamovych
 */
public class AwtIdlePolicy implements IdlePolicy {
    /**
     * Forces toolkit to synchronize with the native windowing sub-system, flushing all pending work and waiting for all the events to be processed. This method
     * guarantees that after return no additional Java events will be generated, unless cause by user.
     * <p>
     * This method allows to write tests without explicit timeouts or wait for some event. Example:
     * 
     * <pre>
     * Frame f = ...;
     * f.setVisible(true);
     * ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
     * </pre>
     * <p>
     * After realSync, <code>f</code> will be completely visible on the screen, its getLocationOnScreen will be returning the right result and it will be the
     * focus owner.
     * <p>
     * Another example:
     * 
     * <pre>
     * b.requestFocus();
     * ((SunToolkit) Toolkit.getDefaultToolkit()).realSync();
     * </pre>
     * <p>
     * After realSync, <code>b</code> will be focus owner.
     * <p>
     * Notice that realSync isn't guaranteed to work if recurring actions occur, such as if during processing of some event another request which may generate
     * some events occurs. By default, sync tries to perform as much as {@value MAX_ITERS} cycles of event processing, allowing for roughly {@value MAX_ITERS}
     * additional requests.
     * <p>
     * For example, requestFocus() generates native request, which generates one or two Java focus events, which then generate a serie of paint events, a serie
     * of Java focus events, which then generate a serie of paint events which then are processed - three cycles, minimum.
     */
    public static void realSync() {
        ((SunToolkit) Toolkit.getDefaultToolkit()).realSync();
    }
    
    @Override
    public boolean isIdle() {
        try {
            Toolkit toolkit = Toolkit.getDefaultToolkit();
            ReflectUtils.invoke(toolkit, "syncNativeQueue");
            Boolean isMoreProcessingNecessary = ReflectUtils.invoke(toolkit, "waitForIdle");
            return !isMoreProcessingNecessary;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
